package com.se.service;

import cn.hutool.json.JSONArray;
import com.se.dao.es.ActESDao;
import com.se.dao.mysql.*;
import com.se.domain.dto.ImageFileDTO;
import com.se.domain.mysql.ActivityDO;
import com.se.domain.mysql.CategoryDO;
import com.se.domain.mysql.ImgDO;
import com.se.domain.request.param.CreateActParam;
import com.se.domain.request.param.UpdateActParam;
import com.se.enums.ResultCode;
import com.se.exception.ResultException;
import com.se.util.MyDateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.ParseException;
import java.util.*;

@Service
public class ActPublishService {
    @Autowired
    WxOpenService wxOpenService;
    @Autowired
    ActService actService;
    @Autowired
    ActDao actDao;
    @Autowired
    CatDao catDao;
    @Autowired
    ApplyDao applyDao;
    @Autowired
    ActESDao actESDao;
    @Autowired
    QuestionDao questionDao;
    @Autowired
    ImgDao imgDao;

    public ActivityDO createAct(CreateActParam param, MultipartFile[] files, Long userId) throws ResultException {
        this.checkCatParam(param.getCatIds());

        //检验image并生成URL和filePath
        if(files != null && files.length > 0){
            ActivityDO[] actArr = new ActivityDO[1];
            ImageFileDTO[] imgDTOArray = imgDao.generateImageFileDTO(3, 1024*1024*5, files);
            List<ImgDO> imgDOList = new ArrayList<>();
            for (ImageFileDTO dto : imgDTOArray) {
                imgDOList.add(new ImgDO(dto));
            }
            imgDao.saveImgFileAspect(
                    ()->{
                        imgDao.insertAll(imgDOList);
                        StringJoiner joiner = new StringJoiner(",");
                        for (ImgDO imgDO : imgDOList) {
                            joiner.add(imgDO.getImgId().toString());
                        }
                        param.setImgIds(joiner.toString());
                        actArr[0] = actDao.createAct(param, userId);
                    },
                    imgDTOArray
            );
            return actArr[0];
        }else {
            return actDao.createAct(param, userId);
        }

    }

    private void checkCatParam(List<Long> catIds) throws ResultException {
        //检查catIds
        List<CategoryDO> categoryDOList = catDao.listByCatIds(catIds);
        if(categoryDOList.size() != catIds.size()){
            throw new ResultException(ResultCode.NO_OBJECT.getCode(), "类型不存在");
        }
    }

    public void updateAct(UpdateActParam param, MultipartFile[] files, Long userId) throws ResultException {
        this.checkCatParam(param.getCatIds());

        ActivityDO activityDO = actService.checkModifyAct(param.getActId(), userId);

        //检查是否能修改
        if(activityDO.getPublish()){
            //处于发布中
            throw new ResultException(ResultCode.PUBLISH_NO_UPDATE);
        }
        if(applyDao.existByQnId(activityDO.getQnId())){
            //有人报名了
            throw new ResultException(ResultCode.APPLY_NO_UPDATE);
        }
        //问卷有更改，给qnId置空
        if(!Objects.equals(activityDO.getQnJson(), new JSONArray(param.getQn()).toString())){
            activityDO.setQnId(null);
        }

        //确定保留的imgId和需要删除的imgId
        List<Long> delImgIds = new ArrayList<>(activityDO.getImgIdList());
        delImgIds.removeAll(param.getImgIdList());

        ImageFileDTO[] imgDTOArray = imgDao.generateImageFileDTO(3, 1024*1024*5, files);
        List<ImgDO> imgDOList = new ArrayList<>();
        for (ImageFileDTO dto : imgDTOArray) {
            imgDOList.add(new ImgDO(dto));
        }

        imgDao.saveImgFileAspect(
                ()->{
                    imgDao.insertAll(imgDOList);
                    StringJoiner joiner = new StringJoiner(",");
                    for (Long imgId : param.getImgIdList()) {
                        joiner.add(imgId.toString());
                    }
                    for (ImgDO imgDO : imgDOList) {
                        joiner.add(imgDO.getImgId().toString());
                    }
                    //真实删除图片文件项和数据项
//                    imgDao.delByIdList(delImgIds);

                    param.setImgIds(joiner.toString());

                    activityDO.update(param);

                    actDao.updateAct(activityDO);
                },
                imgDTOArray
        );


    }


    public void publishAct(Long actId, Long userId) throws ResultException, IOException, ParseException {
        ActivityDO activityDO = actService.checkModifyAct(actId, userId);

        //时间检查,活动已经开始不能发布
        if(MyDateUtil.beforeCurrentTime(activityDO.getStartTime())){
            throw new ResultException(ResultCode.TIME_INVALID);
        }

        if(!activityDO.getPublish()){
            actDao.publishByActId(actId);
            //ES添加项，创建题目项，只要发布就会创建新的qnId，之前的报名记录全部无效
            try {
                Long qnId = questionDao.createQn(actId, activityDO.getQnJson());
                if(qnId != null)
                    actDao.updateQnIdByActId(qnId, actId);
                actESDao.createAct(activityDO);
            }catch (Exception e){
                actDao.cancelPublishByActId(actId);
                throw e;
            }
        }


    }

    public void cancelPublishAct(Long actId, Long userId) throws ResultException, ParseException, IOException {
        ActivityDO activityDO = actService.checkModifyAct(actId, userId);

        //时间检查，活动已经开始不能取消
        if(MyDateUtil.beforeCurrentTime(activityDO.getStartTime())){
            throw new ResultException(ResultCode.TIME_INVALID);
        }

        //取消活动，同时qnId置null，applyNum置0，之前的记录全部无效
        actDao.cancelPublishByActId(actId);
        //ES 删除项
        try {
            actESDao.removeAct(actId);
        }catch (IOException e) {
            actDao.publishByActId(actId);
            throw e;
        }

        //提醒
        wxOpenService.notifyActCancel(activityDO);
    }


    public void deleteAct(Long actId, Long userId) throws ResultException {
        ActivityDO activityDO = this.actService.checkModifyAct(actId, userId);

        if(activityDO.getPublish()){
            throw new ResultException(ResultCode.PUBLISH_NO_DELETE);
        }

        actDao.deleteByCatId(actId);
    }
}
